package com.sfexpress.tools;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;

import com.google.common.base.Function;
import com.google.common.collect.Maps;
import com.sfexpress.tools.entity.ConsCheckResult;
import com.sfexpress.tools.entity.ConsCheckResult.ItemResult;
import com.sfexpress.tools.entity.ConsCheckResult.ConflictItem;
import com.sfexpress.tools.entity.MysqlColumnConstInfo;
import com.sfexpress.tools.entity.MysqlTableInfo;
import com.sfexpress.tools.utils.Pair;
import com.sfexpress.tools.utils.SetUtil;

public class MysqlColumnConstChecker extends AbstractChecker {
	
	public void checkConsistency(MysqlTableInfo pvTableInfo, MysqlTableInfo gvTableInfo, ConsCheckResult result) {
		
		logger.info("开始执行列约束一致性校验 ...");
		
		Map<String, MysqlColumnConstInfo> pvColLevelConstMap = getColLevelConstMap(pvTableInfo.getColLevelConstInfoList());
		Map<String, MysqlColumnConstInfo> gvColLevelConstMap = getColLevelConstMap(gvTableInfo.getColLevelConstInfoList());
	
		Set<String> pvTbLevelConstSet = pvColLevelConstMap.keySet();
		Set<String> gvTbLevelConstSet = gvColLevelConstMap.keySet();
		
		Set<String> newItems = SetUtil.getDiffSet(gvTbLevelConstSet, pvTbLevelConstSet);
		Set<String> deletedItems = SetUtil.getDiffSet(pvTbLevelConstSet, gvTbLevelConstSet);
		
		if(newItems.size() > 0) {
//			result.setCoincident(false);
			logger.warn("检测到灰度版本表存在新的列约束 : " + Arrays.toString(newItems.toArray()));
			result.getColConstCheckResult().setCoincident(false);
			for(String newItem : newItems) {
				result.getColConstCheckResult().getNewItems().add(gvColLevelConstMap.get(newItem));
			}
		}
		
		if(deletedItems.size() > 0) {
//			result.setCoincident(false);
			logger.warn("检测到灰度版本没有的列约束 : " + Arrays.toString(deletedItems.toArray()));
			result.getColConstCheckResult().setCoincident(false);
			for(String delItem : deletedItems) {
				result.getColConstCheckResult().getDeletedItems().add(pvColLevelConstMap.get(delItem));
			}
		}
		
		Set<String> commItems = SetUtil.getInterSet(pvTbLevelConstSet, gvTbLevelConstSet);
		
		for(String item : commItems) {
			MysqlColumnConstInfo pvItem = pvColLevelConstMap.get(item);
			MysqlColumnConstInfo gvItem = gvColLevelConstMap.get(item);
			if(!checkConsistency(pvItem, gvItem, result)) {
//				result.setCoincident(false);
				logger.warn("检测到有不一致的列约束 : " );
				logger.warn("From 生产版本库 : " + pvItem);
				logger.warn("From 灰度版本库 : " + gvItem);
				result.getColConstCheckResult().setCoincident(false);
				result.getColConstCheckResult().getConflictItems().add(new Pair<MysqlColumnConstInfo, MysqlColumnConstInfo>(pvItem, gvItem));
			}
		}
		
		logger.info("列约束一致性校验结束!");
		
	}
	
	private boolean checkConsistency(MysqlColumnConstInfo pvColLevelConstInfo, MysqlColumnConstInfo gvColLevelConstInfo, ConsCheckResult result) {
		
		boolean flag = true;
		String key = pvColLevelConstInfo.getConstraintName();
		ItemResult<MysqlColumnConstInfo> colConstInfoCheckResult = result.getColConstCheckResult();
		if(!StringUtils.equals(pvColLevelConstInfo.getColumnName(), gvColLevelConstInfo.getColumnName())) {
			flag = false;
			colConstInfoCheckResult.addConflictItem(key, new ConflictItem(key, "COLUMN_NAME", pvColLevelConstInfo.getColumnName(), gvColLevelConstInfo.getColumnName()));
		}
		if(!StringUtils.equals(pvColLevelConstInfo.getRefTableSchema(), gvColLevelConstInfo.getRefTableSchema())) {
			flag = false;
			colConstInfoCheckResult.addConflictItem(key, new ConflictItem(key, "REF_TABLE_SCHEMA", pvColLevelConstInfo.getRefTableSchema(), gvColLevelConstInfo.getRefTableSchema()));
		}
		if(!StringUtils.equals(pvColLevelConstInfo.getRefTableName(), gvColLevelConstInfo.getRefTableName())) {
			flag = false;
			colConstInfoCheckResult.addConflictItem(key, new ConflictItem(key, "REF_TABLE_NAME", pvColLevelConstInfo.getRefTableName(), gvColLevelConstInfo.getRefTableName()));
		}
		if(!StringUtils.equals(pvColLevelConstInfo.getRefColumnName(), gvColLevelConstInfo.getRefColumnName())) {
			flag = false;
			colConstInfoCheckResult.addConflictItem(key, new ConflictItem(key, "REF_COLUMN_NAME", pvColLevelConstInfo.getRefColumnName(), gvColLevelConstInfo.getRefColumnName()));
		}
		return flag;
	}
	
	private Map<String, MysqlColumnConstInfo> getColLevelConstMap(List<MysqlColumnConstInfo> colLevelConstList) {
		return Maps.uniqueIndex(colLevelConstList, new Function<MysqlColumnConstInfo, String>() {

			@Override
			public String apply(MysqlColumnConstInfo item) {
				return item.getConstraintName();
			}
		});
	}

}
